package com.netease.demo.shortvideo.uploader.model;


import com.netease.demo.shortvideo.model.VideoItem;
import com.netease.demo.shortvideo.server.entity.VideoInfoEntity;
import com.netease.demo.shortvideo.uploader.constant.UploadState;

import java.util.ArrayList;
import java.util.List;


/**
 * Created by zhukkun on 2/22/17.
 */
public class UploadDataAccessor extends DataAccessor<VideoItem> {

    List<DataChangeObserver> observers = new ArrayList<>();

    public interface DataChangeObserver{

        void onDataSetChanged(List<VideoItem> data);

    }

    public void addObserver(DataChangeObserver observer){
        observers.add(observer);
    }

    public void removeObserver(DataChangeObserver observer){
        observers.remove(observer);
    }

    public void sendDataChangeMsg(){
        for (int i = 0; i < observers.size(); i++) {
            observers.get(i).onDataSetChanged(getTotalData());
        }
    }

    /**
     * 从服务端拉取的数据
     */
    List<VideoItem> cloudItemList = new ArrayList<>();
    /**
     * 本地数据
     * 注意: 当某项上传成功后,再次拉取全部云端数据时,会将该项从localItems中移除,在cloudItems中添加
     */
    List<VideoItem> localItemList = new ArrayList<>();

    /**
     *  转码中的数据列表, 用于轮询转码状态
     */
    List<VideoItem> transCodingItems = new ArrayList<>();

    /**
     * 获取 云端数据 + 本地数据
     * @return 全部的列表数据,可用于展示
     */
    public List<VideoItem> getTotalData(){
        List<VideoItem> total = new ArrayList<>(cloudItemList);
        total.addAll(localItemList);
        return total;
    }

    public int getTotalCount() {
        return cloudItemList.size() + localItemList.size();
    }

    public List<VideoItem> getUploadList() {
        return localItemList;
    }

    //上传完成的数量
    int sucNumber = 0;

    public void addLocalVideoItems(List<VideoItem> videoItems){
        this.localItemList.addAll(videoItems);
        init(videoItems, true);
        sendDataChangeMsg();
    }

    public void setCloudVideoItems(List<VideoItem> videoItems){
        //支持多端登录,防止在本端查询转码的视频已在他端删除, 故重新拉取时,移除转码查询列表中的数据
        this.transCodingItems.removeAll(cloudItemList);
        this.cloudItemList.clear();
        this.cloudItemList.addAll(videoItems);
        init(videoItems, false);
        sendDataChangeMsg();
    }

    @Override
    public void init() {
        sucNumber = 0;
    }

    /**
     *
     * @param videoItems
     * @param isLocal 是否为本地数据
     */
    public void init(List<VideoItem> videoItems, boolean isLocal){

        for (VideoItem videoItem: videoItems) {
            if(!isLocal){
                //VideoInfoEntity 为上传成功后的项 数据从云端拉取
                VideoInfoEntity entity = videoItem.getEntity();
                switch (entity.getStatus()){
                    case 20:
                        videoItem.setState(UploadState.STATE_TRANSCODE_FAIL);
                        break;
                    case 30:
                        videoItem.setState(UploadState.STATE_TRANSCODEING);
                        transCodingItems.add(videoItem);
                        break;
                    case 40:
                        videoItem.setState(UploadState.STATE_TRANSCODE_COMPLETE);
                        break;
                }
                videoItem.setVid(entity.getVid());
                videoItem.setId("remote"+ entity.getVid());
            } else if (!videoItem.getId().startsWith("local")){
                //由于产品定义 同一个文件可以反复上传,故使用时间戳来重设ID,用于区分不同的视频文件
                videoItem.setId("local" + videoItem.getId()+ System.currentTimeMillis());
                UploadDbHelper.saveToDb(videoItem);
            }
        }
    }

    /**
     * 也可改用HashMap<id, item> 存储,来提高速度
     * @param id
     * @return
     */
    @Override
    public VideoItem acquire(String id) {

        for (int i = 0; i < localItemList.size(); i++) {
            if(localItemList.get(i).getId().equals(id)){
                return localItemList.get(i);
            }
        }

        for (int i = 0; i < cloudItemList.size(); i++) {
            if(cloudItemList.get(i).getId().equals(id)){
                return cloudItemList.get(i);
            }
        }

        return null;
    }

    public VideoItem acquireByVid(long vid){

        for (int i = 0; i < cloudItemList.size(); i++) {
            if(cloudItemList.get(i).getVid() == vid){
                return cloudItemList.get(i);
            }
        }

        for (int i = 0; i < localItemList.size(); i++) {
            if(localItemList.get(i).getVid() == vid){
                return localItemList.get(i);
            }
        }
        return null;
    }

    @Override
    public void save(String id, VideoItem object) {

        if(object.getState() == UploadState.STATE_UPLOAD_COMPLETE){
            sucNumber++;
        }
        if(object.getState() == UploadState.STATE_TRANSCODEING){
            transCodingItems.add(object);
        }
    }

    public List<Long> getTranscodingVidList(){
        List<Long> vidList=  new ArrayList<>();

        for (VideoItem items:transCodingItems) {
            vidList.add(items.getVid());
        }
        return vidList;
    }

    public List<VideoItem> getTranscodingItems(){
        return transCodingItems;
    }

    public boolean isFullySuccess(){
        return localItemList.size() == sucNumber;
    }

    /**
     * 是否有等待上传的任务
     * @return
     */
    public boolean hasWaitTask() {
        for (int i = 0; i < localItemList.size(); i++) {
            if(localItemList.get(i).getState() == UploadState.STATE_WAIT){
                return true;
            }
        }
        return false;
    }


    public VideoItem removeTranscodeItemByVid(long vid) {
        for (int i = 0; i < transCodingItems.size(); i++) {
            if(vid == transCodingItems.get(i).getVid()){
                return transCodingItems.remove(i);
            }
        }
        return null;
    }

    public void removeItem(VideoItem videoItem) {

        localItemList.remove(videoItem);
        cloudItemList.remove(videoItem);

        if(videoItem.getVid()!= 0){
            //尝试从转码查询队列中移除
            removeTranscodeItemByVid(videoItem.getVid());
        }

        if(videoItem.getId().startsWith("local")){
            switch (videoItem.getState()){
                case UploadState.STATE_UPLOAD_COMPLETE:
                case UploadState.STATE_TRANSCODEING:
                case UploadState.STATE_TRANSCODE_COMPLETE:
                case UploadState.STATE_TRANSCODE_FAIL:
                    sucNumber--;
                    break;
            }
            UploadDbHelper.removeItemFromDb(videoItem);
        }

        sendDataChangeMsg();
    }

}
